package com.shuyu.framework.web.service;

import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shuyu.common.core.domain.entity.Customer;
import com.shuyu.common.core.domain.model.LoginUser;
import com.shuyu.common.exception.ServiceException;
import com.shuyu.common.exception.user.UserPasswordNotMatchException;
import com.shuyu.common.utils.DesCode;
import com.shuyu.common.utils.nft.NFTUtils;
import com.shuyu.common.utils.nft.domain.WalletVo;
import com.shuyu.common.utils.uuid.UUID;
import com.shuyu.domain.CustomerWx;
import com.shuyu.framework.security.context.AuthenticationContextHolder;
import com.shuyu.service.CustomerService;
import com.shuyu.service.CustomerWxService;
import com.shuyu.vo.CustomerVo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 登录校验方法
 * 
 * @author ruoyi
 */
@Component
public class CustomerLoginService
{
    @Resource
    private CustomerWxService customerWxService;
    @Resource
    private CustomerService customerService;
    @Resource
    private TokenService tokenService;

    @Resource
    @Qualifier("CustomerAuthenticationManager")
    private AuthenticationManager authenticationManager;

    /**
     * 登录验证
     * 
     * @param customer 用户换取 access_token 的 code
     * @return 结果
     */
    public String customerLogin(CustomerVo customerVo)
    {
        // 用户验证
        Authentication authentication = null;
        try
        {
            String openId = customerVo.getOpenid();
            int count = customerWxService.count(new LambdaQueryWrapper<CustomerWx>().eq(CustomerWx::getOpenId, openId));
            Customer customer;
            //说明用户已经通过微信快捷登录注册了
            if(count>0){
                CustomerWx customerWx = customerWxService.getOne(new LambdaQueryWrapper<CustomerWx>().eq(CustomerWx::getOpenId, openId).last("limit 1"));
                customer = customerService.getOne(new LambdaQueryWrapper<Customer>().eq(Customer::getDelFlag,0).eq(Customer::getThirdId, customerWx.getId()).last("limit 1"));
            }else {
                CustomerWx customerWx = new CustomerWx(customerVo.getUnionid(), openId, customerVo.getNickname(), customerVo.getSex(), customerVo.getProvince(),
                        customerVo.getCity(), customerVo.getCountry(), customerVo.getHeadimgurl(), new Date());
                customerWxService.save(customerWx);
                String username = MD5.create().digestHex16(UUID.fastUUID().toString());
                String saltVal = MD5.create().digestHex(username+new Date().getTime());
                WalletVo wallet = NFTUtils.createWallet();
                customer = new Customer(username, DesCode.encrypt(customerVo.getNickname()), 0, customerWx.getId(), saltVal, wallet.getAddress(), wallet.getPrivateKey(), customerWx.getHeadimgurl(), new Date());
                customerService.save(customer);
            }
            String username = customer.getUsername();
            String password = customer.getSaltVal();


            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用CustomerDetailsServiceImpl.loadUserByUsernam
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
            AuthenticationContextHolder.clearContext();
        }
//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }


    public String testToken(String openId)
    {
        // 用户验证
        Authentication authentication = null;
        try
        {
            CustomerWx customerWx = customerWxService.getOne(new LambdaQueryWrapper<CustomerWx>().eq(CustomerWx::getOpenId, openId).last("limit 1"));
            Customer customer = customerService.getOne(new LambdaQueryWrapper<Customer>().eq(Customer::getThirdId, customerWx.getId()).last("limit 1"));
            String username = customer.getUsername();
            String password = customer.getSaltVal();


            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用CustomerDetailsServiceImpl.loadUserByUsernam
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
            AuthenticationContextHolder.clearContext();
        }
//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }
}
